<!--
 * @Author: 孙文豪
 * @Description: 
 * @Date: 2022-12-29 16:06:58
 * @LastEditTime: 2023-01-09 16:56:02
 * @LastEditors: 孙文豪
-->
<template>
  <div class="swh-pagination-box">
    <p
      class="pagebtn other-btn"
      :class="{ disable: actval === 1 }"
      @click="PageBtn(actval === 1, true, true)"
    >
      首页
    </p>
    <p
      class="pagebtn other-btn"
      :class="{ disable: actval === 1 }"
      @click="PageBtn(actval === 1, true)"
    >
      上一页
    </p>
    <p
      class="pagebtn"
      :class="
        actval == item
          ? 'active'
          : item === ellipsis
          ? index === 1
            ? 'ellipsisL'
            : 'ellipsisR'
          : ''
      "
      v-for="(item, index) in showList"
      @click="getCurrentPage(item, index)"
      :key="`${index}${item}`"
    >
      {{ item }}
    </p>
    <p
      class="pagebtn other-btn"
      :class="{ disable: actval === inCountPage }"
      @click="PageBtn(actval === inCountPage, false)"
    >
      下一页
    </p>
    <p
      class="pagebtn other-btn"
      :class="{ disable: actval === inCountPage }"
      @click="PageBtn(actval === inCountPage, false, true)"
    >
      末页
    </p>
    <div class="pagebtn-input other-btn" v-if="isJumpFunction">
      <p>前往</p>
      <input
        class="swh-input"
        type="text"
        v-model="jumpNum"
        @keydown.enter="getCurrentPage(jumpNum)"
      />
      <p>页</p>
    </div>
    <div class="page-num" v-if="inPageNumList.length">
      <swh-drop-down
        :dataList="inPageNumList"
        :defaultValue="inCurrentPage"
        :dropDownZindex="dropDownZindex"
        @getActiveValue="activeValueChange"
      ></swh-drop-down>
    </div>
  </div>
</template>
<script>
import { watch, reactive, toRefs, onMounted } from "vue";
import { getNumRangeArr } from "@/utils/common.js";
export default {
  name: "SwhPagination",
  props: {
    total: {
      //数据总量
      type: Number,
      default: 0,
      explain: "数据总量",
      otherVal: "---",
    },
    aroundRange: {
      //总共显示页码
      type: Number,
      default: 5,
      explain: "除省略号外实际显示的页码数量，总页数小于10无省略号",
      otherVal: "5 ~ 总页数 / 2",
    },
    activePageNum: {
      //初始当前值
      type: Number,
      default: 1,
      explain: "当前选中的页码",
      otherVal: "1 ~ 总页数",
    },
    fastSwitchNum: {
      //快速切换数值
      type: Number,
      default: 2,
      explain: "快速切换数值，点击省略号部分，向前向后一次移动的页数",
      otherVal: "2 ~ n",
    },
    eachDataSize: {
      //每页显示的个数
      type: Number,
      default: 10,
      explain: "每页显示的数据量",
      otherVal: "1 ~ n",
    },
    pageNumList: {
      type: Array,
      default: () => {
        return [];
      },
      explain: "每页显示数量选择（配置后显示）",
      otherVal: "[10,20,50,100]",
    },
    isJumpFunction: {
      type: Boolean,
      default: true,
      explain: "是否显示直接跳转页数功能",
      otherVal: false,
    },
    dropDownZindex: {
      type: Number,
      default: 1,
      explain: "选择每页显示数量下拉框层级",
      otherVal: "---",
    },
    getCurrentPage: {
      type: Function,
      explain: "监听当前选中页数事件",
    },
    getDataSize: {
      type: Function,
      explain: "获取选中每页显示数量",
    },
  },
  setup(props, ctx) {
    const data = reactive({
      ellipsis: "···",
      jumpNum: 1,
      showList: [], //显示的列表
      actval: 0,
      inFastSwitchNum: props.fastSwitchNum < 2 ? 2 : props.fastSwitchNum, // 对快速切换进行验证
      inEachPageNum: props.eachDataSize < 1 ? 1 : props.eachDataSize,
      inCountPage: 0, //总页数
      inAroundRange: 0,
      inPageNumList: [], //传递给下拉框拼接文案
      inCurrentPage: "", //传递给下拉框默认项
    });
    // 监听每页显示个数
    watch(
      () => props.eachDataSize,
      () => {
        updateTotalPage();
        getShowlist(data.actval);
      }
    );
    // 监听页数变化
    watch(
      () => data.actval,
      () => {
        ctx.emit("getCurrentPage", data.actval);
        getShowlist(data.actval);
      }
    );
    onMounted(() => {
      updateTotalPage();
      for (let i = 0; i < props.pageNumList.length; i++) {
        data.inPageNumList.push(`${props.pageNumList[i] || 1}条/页`);
      }
      data.inCurrentPage = `${props.eachDataSize || 1}条/页`;
    });
    // 更新总页数时
    const updateTotalPage = () => {
      const inPageNum = parseInt(props.eachDataSize);
      data.inEachPageNum = inPageNum < 1 ? 1 : inPageNum; // 先计算每页显示个数
      data.inCountPage = Math.ceil(props.total / data.inEachPageNum); // 计算总页数
      data.actval =
        props.activePageNum > data.inCountPage ? 1 : props.activePageNum || 1; // 初始化当前页1~总页数
      data.jumpNum = data.actval;
      data.inAroundRange = initInAroundRange(); // 初始化显示范围
    };
    // 计算范围
    const initInAroundRange = () => {
      // 总页数小于10不设置范围五省略号，
      // 范围最小5
      // 最大不得超过总页数一半
      const CountPageUpLimit = Math.floor(data.inCountPage / 2);
      return data.inCountPage < 10
        ? 0
        : props.aroundRange < 5
        ? 5
        : props.aroundRange > CountPageUpLimit
        ? CountPageUpLimit
        : props.aroundRange;
    };
    // 获取显示的分页器数据
    const getShowlist = (val) => {
      const range = Math.floor(data.inAroundRange / 2);
      //  前部分判断显示
      if (!data.inAroundRange) {
        data.showList = data.inCountPage;
        return;
      }
      let newArr = [];
      if (val > range + 1) {
        // 前部分增加...的情况
        newArr = [1, data.ellipsis];
        if (val > data.inCountPage - range) {
          // 前部分增加...时 处理后部分
          newArr.push(...getNumRangeArr(data.inCountPage - range, range - 1));
        } else {
          // 前部分增加...时 处理前部分
          newArr.push(...getNumRangeArr(val, range - 1));
        }
      } else {
        // 不增加的情况...  处理前部分
        newArr.push(1);
        newArr.push(...getNumRangeArr(range + 1, range - 1));
      }
      // 下面只处理后部分
      const lastNum = newArr[newArr.length - 1];
      const Difference = data.inCountPage - lastNum;
      if (Difference > 1) {
        // 小于总数过多，拼接...和末尾数
        newArr.push(data.ellipsis, data.inCountPage);
      } else {
        // 比总数小1位直接拼接末位数
        newArr.push(data.inCountPage);
      }
      data.showList = newArr;
    };
    // 点击当前页
    const getCurrentPage = (pageVal, index) => {
      let inPageVal = parseInt(pageVal || 1);
      if (!Number.isNaN(inPageVal)) {
        // 校验当前选中页码，1到总数之间
        inPageVal =
          inPageVal > 1 ? (inPageVal > data.inCountPage ? 1 : inPageVal) : 1;
        data.actval = inPageVal;
      } else {
        // 点击省略号处理
        const num_a = data.showList[index - 1];
        const num_b = data.showList[index + 1];
        if (num_a == 1) {
          // 前部分
          if (num_b - num_a > data.inFastSwitchNum) {
            data.actval = num_b - data.inFastSwitchNum; // 前进指定页数
          } else {
            data.actval = num_a + 1; // 页数不足，第2页
          }
        } else {
          // 后部分
          if (num_b - num_a > data.inFastSwitchNum) {
            data.actval = num_a + data.inFastSwitchNum; // 后退指定页数
          } else {
            data.actval = num_b - 1; // 页数不足，倒数第2页
          }
        }
      }
      data.jumpNum = data.actval;
    };
    //点击左右按键
    const PageBtn = (isDisable, sign, sign_a) => {
      if (isDisable) return; //判断是否禁用
      if (sign) {
        //上一页
        if (data.actval !== 1) {
          if (sign_a) {
            data.actval = 1; //首页
          } else {
            data.actval--; // 上一页
          }
        }
      } else {
        //下一页
        if (data.actval !== data.inCountPage) {
          if (sign_a) {
            data.actval = data.inCountPage; //末页
          } else {
            data.actval++; //下一页
          }
        }
      }
      data.jumpNum = data.actval;
    };
    // 选中值变化
    const activeValueChange = (val) => {
      ctx.emit("getDataSize", parseInt(val));
    };
    return {
      PageBtn,
      getCurrentPage,
      activeValueChange,
      ...toRefs(data),
    };
  },
};
</script>
<style lang="less" scoped>
.swh-pagination-box {
  -moz-user-select: none; /** 火狐*/
  -webkit-user-select: none; /** webkit浏览器*/
  -ms-user-select: none; /** IE10*/
  -khtml-user-select: none; /** 早期浏览器*/
  user-select: none;
  overflow: hidden;
  .pagebtn {
    float: left;
    font-size: 14px;
    line-height: 30px;
    margin: 0 2px;
    width: 36px;
    border: 1px solid rgb(227, 227, 227);
    text-align: center;
    border-radius: 4px;
    transition: 0.3s;
    color: @HSB;
    cursor: pointer;
    &.other-btn {
      width: auto;
      padding: 0 10px;
      &.disable {
        color: @HSC;
        background: @HSF;
        border: 1px solid @HSE;
        &:hover {
          cursor: no-drop;
        }
      }
    }
    &:hover {
      background: @TSD;
      border: 1px solid @TSC;
      color: @TSB;
    }
    &.active {
      background: @TSA;
      border: 1px solid @TSA;
      color: @HSE;
    }
  }
  .ellipsisR {
    position: relative;
    &:hover {
      &::before {
        content: "⋙";
        position: absolute;
        line-height: 28px;
        background: @TSD;
        width: 100%;
        height: 100%;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
      }
    }
  }
  .ellipsisL {
    position: relative;
    &:hover {
      &::before {
        content: "⋘";
        position: absolute;
        line-height: 28px;
        background: @TSD;
        width: 100%;
        height: 100%;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
      }
    }
  }
  .pagebtn-input {
    float: left;
    margin-left: 70px;
    p {
      float: left;
      line-height: 30px;
      font-size: 14px;
    }
    .swh-input {
      margin: 0 5px;
      width: 36px;
      line-height: 30px;
      text-align: center;
      float: left;
      outline: none;
      box-sizing: border-box;
      border: 1px solid rgb(227, 227, 227);
      border-radius: 4px;
    }
  }
  .page-num {
    float: right;
    margin-left: 50px;
  }
}
</style>
